<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>递归复制</title>
</head>
<body>

</body>
<script>
    // 在实现深度克隆时，使用 WeakMap 而不是 Map 主要是出于以下几个原因：
    // 1. 垃圾回收
    //     WeakMap： WeakMap 的键是弱引用，这意味着如果没有其他引用指向这些键，垃圾回收机制会自动回收这些键及其对应的值。
    //     这有助于防止内存泄漏，特别是在处理大量对象时。如果使用 WeakMap，一旦我们不再需要深拷贝的对象，垃圾回收机制可以自动回收相关内存。

    //     Map： Map 的键是强引用，只要 Map 中存在键的引用，就不会被垃圾回收。这可能导致内存泄漏，尤其是在处理大量对象或者长时间运行的应用程序中，
    //     因为 Map 会保留所有的键，直到 Map 本身被显式地清除或销毁。

    // 2. 使用场景
    //     WeakMap： 适用于将对象用作键的场景，并且希望这些对象在没有其他引用时可以被垃圾回收。
    //     例如，在深度克隆过程中，我们只需要在克隆期间跟踪对象的引用，以避免循环引用问题。在这种情况下，使用 WeakMap 更加合适，因为我们希望这些临时的引用能够在克隆过程结束后自动清除。

    //     Map： 适用于需要长期持有键值对的场景，并且不希望键被垃圾回收。
    //     例如，如果你需要持久地存储一些对象的关联数据，那么使用 Map 是更合适的选择。


    // 示例
    //     假设我们有以下代码展示了 WeakMap 和 Map 在处理垃圾回收时的区别

    let weakMap = new WeakMap();
    let map = new Map();
    (function () {
        let obj = { key: 'value' }
        weakMap.set(obj, 'some value')
        map.set(obj, 'some value')
        
        // 在这里 obj 依然存在，作为 weakMap 和 map 的键
        console.log(weakMap.has(obj)); // true
        console.log(map.has(obj)); // true
    })();

    // 一旦函数作用域结束，obj 被销毁
    // WeakMap 不再持有 obj 的引用，允许垃圾回收
    // Map 仍然持有 obj 的引用，不允许垃圾回收

    console.log(weakMap.has({ key: 'value' })); // false, 因为 WeakMap 只保留弱引用
    console.log(map.has({ key: 'value' })); // false, 新对象，与 map 中存储的对象不同
</script>
</html>